5. Name That Tune!#
In this lab we will explore the basic relationship between sound and a mathematical description of sound using sine waves.
First we can observe that sound is created by periodic vibration of the air as caused for example by a vibrating guitar string.
from IPython.display import YouTubeVideo
YouTubeVideo('tVYQRC1-D54')
How can we use a sequence of numbers to create a tune such as “We Shall Overcome”?
from IPython.display import YouTubeVideo
YouTubeVideo('pUpq2WPLvbg')
STEP ONE
Pure tones can be modelled sine waves. The amplitude of a sine wave (high high up and down it oscillates) is proportional to the volume of the sound. The Frequency of a sine wave is defined as the number of times a wave completes its up and down cycle in one second. The higher the frequency of a sound wave, the hiher the pitch. Use the function defined in the next cell to check what happens to a sinewave if we change its frequency.import numpy as np
def sinewave(frequency):
#-----------CREATE THE SOUND WAVE-------------------
sampling_rate=44100 #how many times we take a measurement each second
t = np.linspace(0,1,sampling_rate) # take 44100 samples in 1 second;
sound_wave=np.sin(frequency* 2*np.pi* t) # mathematical definition of a sine wave
#----------PLOT THE SOUND WAVE----------------------
import matplotlib.pyplot as plt
fig=plt.figure(figsize=(2,1))
plt.plot(t,sound_wave)
plt.xlabel("seconds")
return
sinewave(1) #frequency=1 and 1 cycle per second
sinewave(2) #frequency=2 and 2 cycles per second
sinewave(3) #frequency=3 and 3 cycles per second
sinewave(20) #frequency=20 and 20 cycles per second
STEP TWO
If an object vibrates at high enough frequency, it creates a sound wave that we can hear. The following function converts a frequency into a sinewave and then into an audible sounddef play(freq):
import numpy as np
from IPython.display import Audio #library used to create sounds
sampling_rate = 44100 # <- rate of sampling
t = np.linspace(0, 2, sampling_rate) # <- setup time values
sound_wave = np.sin(2 * np.pi * freq * t) # <- sine function formula
return Audio(sound_wave, rate=sampling_rate, autoplay=True) # play the generated sound
play(220) # play a sound at 220 hz
Doubling the frequency creates the same note but an octave higher.
play(440) # play a sound at 440 hz
STEP THREE
A musical scale can be created by multipling the first note in the scale by different fractionsimport numpy as np
from IPython.display import Audio
rest=0
do=220
re=9/8*220
mi=5/4*220
fa=4/3*220
so=3/2*220
la=5/3*220
ti=15/8*220
do1=2*220
re1=2*9/8*220
mi1=2*5/4*220
fa1=2*4/3*220
so1=2*3/2*220
la1=2*5/3*220
ti1=2*15/8*220
do2=2*2*220
scale=[do,re,mi,fa,so,la,ti,do1]
twooctavescale=[do,re,mi,fa,so,la,ti,do1,re1,mi1,fa1,so1,la1,ti1,do2]
The following function can play a scale or song for us.
def play(song):
song=np.array(song)
framerate = 44100
t = np.linspace(0, len(song) / 2, round(framerate * len(song) / 2))[:-1]
song_idx = np.floor(t * 2).astype(int)
data = np.sin(2 * np.pi * song[song_idx] * t)
return Audio(data, rate=framerate, autoplay=True)
play(scale)
play(twooctavescale)
STEP FOUR
We can create tunes by arranging notes in a scale.weshallovercome = [so, so , la, la, so, fa,mi,rest,so, so , la, la, so, fa,mi,rest,so,so,la,ti,do1,do1,re1,re1,ti,la,ti,la,so,so,la,ti,do1,do1,ti,la,so,so,rest,rest,la,la,so,fa,mi,mi,rest,rest,so,so,do,fa,mi,mi,re,re,do,do,do,do,rest,rest]
play(weshallovercome)